// /* eslint-disable */
/**
 * 导出稼动率报表
 */
import XLSX from 'xlsx'
import XLSXStyle from 'xlsx-style'
import _ from 'lodash'
import { saveAs } from 'file-saver'

function s2ab (s) {
  const buf = new ArrayBuffer(s.length)
  const view = new Uint8Array(buf)
  for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
  return buf
}

/**
 * 秒转时分秒
 * @param second 秒
 * @returns {string} 时分秒
 */
function getDuration (second) {
  const hours = Math.floor(second / 3600)
  const minutes = Math.floor((second % 3600) / 60)
  const seconds = Math.floor((second % 3600) % 60)
  const duration = `${hours > 9 ? hours : '0' + hours}时${minutes > 9 ? minutes : '0' + minutes}分${seconds > 9 ? seconds : '0' + seconds}秒`
  return duration
}

/**
 * 获取百分比
 * @param val
 * @returns {string | *} 百分比数
 */
function getPercentage (val) {
  return (_.isNil(val) ? 0 : val * 100).toFixed(2)
}

/**
 * 将单元格的字母转换成数字
 * @param a
 * @returns {number}
 */
// function stringTonum (a) {
//   const str = a.toLowerCase().split('')
//   const al = str.length
//   const getCharNumber = function (charx) {
//     return charx.charCodeAt() - 96
//   }
//   let numout = 0
//   let charnum = 0
//   for (let i = 0; i < al; i++) {
//     charnum = getCharNumber(str[i])
//     numout += charnum * Math.pow(26, al - i - 1)
//   }
//   return numout
// }

/**
 * 将单元格的数字转换成字母
 * @param a
 * @returns {number}
 */
const stringArray = []
function numToString (numm) {
  stringArray.length = 0
  const numToStringAction = function (nnum) {
    let num = nnum - 1
    let a = parseInt(num / 26)
    let b = num % 26
    stringArray.push(String.fromCharCode(64 + parseInt(b + 1)))
    if (a > 0) {
      numToStringAction(a)
    }
  }
  numToStringAction(numm)
  return stringArray.reverse().join('')
}

/**
 * 获取需要改变颜色的单元格
 */
function getStyleColName () {
  // 声明一个长度498的数组。 最大选择60天，每天4格。不包括第一条
  const arr = []
  for (let i = 2; i < 500; i++) {
    arr.push(i)
  }
  // 数组按4一组拆分
  const newArr = _.chunk(arr, 4)
  // 过滤掉不需要变色的
  const changeArr = newArr.filter((_, index) => index % 2 === 0)
  // 数组展平转换为响应的字母
  return _.flatten(changeArr).map(item => numToString(item))
}

/**
 * 根据参数返回单元格合并的配置信息
 * @param sc 开始列
 * @param sr 开始行
 * @param ec 结束列
 * @param er 结束行
 * @returns {{s: {r: *, c: *}, e: {r: *, c: *}}}
 * @private
 */
function _getMergeConfig (sc, sr, ec, er) {
  return {
    s: {
      c: sc,
      r: sr
    },
    e: {
      c: ec,
      r: er
    }
  }
}

/**
 * 获取标题的merge信息和显示的文字信息
 * @param data
 * @param theadList
 * @returns {{titleMerge: [], titleDate: []}}
 * @private
 */
function _getTitleInfo (data, theadList) {
  if (!data || !Array.isArray(data) || data.length === 0) return
  const oeeInfos = data[0].oeeInfos
  const date = oeeInfos.map(item => item.date || item.week || item.month)
  const titleMerge = []
  const titleDate = ['设备']
  date.forEach((item, index) => {
    titleMerge.push(_getMergeConfig(index * 4 + 1, 3, index * 4 + 4, 3))
    titleDate.push(theadList[index], '', '', '')
  })
  return { titleMerge, titleDate }
}

/**
 * 获取内容区的合并配置信息
 * @param data
 * @returns []
 * @private
 */
function _getInfoMerge (data) {
  const merge = []
  data.forEach((d, dIndex) => {
    // 合并设备名称
    merge.push(_getMergeConfig(0, dIndex * 7 + 4, 0, (dIndex + 1) * 7 + 3))

    d.oeeInfos.forEach((info, infoIndex) => {
      const leftRow = (infoIndex * 4) + 1
      const rightRow = leftRow + 1
      let leftIndex = dIndex * 7 + 4
      let rightIndex = dIndex * 7 + 4

      for (let i = 0; i < 3; i++) {
        merge.push(_getMergeConfig(leftRow, leftIndex++, leftRow, leftIndex++))
        merge.push(_getMergeConfig(rightRow, rightIndex++, rightRow, rightIndex++))
      }
      merge.push(_getMergeConfig(rightRow, leftIndex, rightRow + 2, leftIndex))
    })
  })
  return merge
}

/**
 * 获取内容区的显示文字信息
 * @param data
 * @returns []
 * @private
 */
function _getInfoData (data) {
  let tableData = []
  data.forEach((d) => {
    let first = [d.deviceName]
    let second = ['']
    let third = ['']
    let fourth = ['']
    let fifth = ['']
    let sixth = ['']
    let seventh = ['']
    d.oeeInfos.forEach((info) => {
      first = first.concat(['时间开动率(A)', `${getPercentage(info.availability)}%`, '计划开机时长', `${getDuration(info.planTime)}`])
      second = second.concat(['', '', '实际加工时长', `${getDuration(info.actualTime)}`])
      third = third.concat(['性能开动率(P)', `${getPercentage(info.performance)}%`, '理论节拍合计', `${getDuration(info.academicBeat)}`])
      fourth = fourth.concat(['', '', '实际节拍合计', `${getDuration(info.actualBeat)}`])
      fifth = fifth.concat(['合格率(Q)', `${getPercentage(info.quality)}%`, '完工数量', '' + info.actualCount])
      sixth = sixth.concat(['', '', '不良数量', '' + info.badCount])
      seventh = seventh.concat(['设备稼动率（OEE）', `${getPercentage(info.oee)}%`, '', ''])
    })
    tableData = tableData.concat([first, second, third, fourth, fifth, sixth, seventh])
  })
  return tableData
}

export function calcColWidth (tableData) {
  const colWidth = [...tableData].map(row => row.map(val => {
    /* 先判断是否为''/undefined */
    if (!val) {
      return {
        'wch': 10
      }
      // 判断是否为中文
    } else if (/[\u4e00-\u9fa5]/.test(val.toString())) {
      return {
        'wch': val.toString().length * 2 > 10 ? val.toString().length * 2 : 10
      }
    } else {
      return {
        'wch': val.toString().length > 10 ? val.toString().length : 10
      }
    }
  }))
  // 每一列取最大宽度
  let result = colWidth[0]
  for (let i = 1; i < colWidth.length; i++) {
    for (let j = 0; j < colWidth[i].length; j++) {
      if (result[j]['wch'] < colWidth[i][j]['wch']) {
        result[j]['wch'] = colWidth[i][j]['wch']
      }
    }
  }
  return result
}

/**
 * 生成样式
 * @private
 */
function _generateStyle (ws) {
  // 居中
  const alignCenter = {
    horizontal: 'center',
    vertical: 'center'
  }
  // 上右下左的border
  const borderAll = { // 单元格外侧框线
    top: {
      style: 'thin'
    },
    bottom: {
      style: 'thin'
    },
    left: {
      style: 'thin'
    },
    right: {
      style: 'thin'
    }
  }
  const font = {
    name: '宋体',
    sz: 12
  }
  // 设置公司名称的样式
  ws['A1'].s = {
    fill: {
      fgColor: {
        rgb: 'FF2F75B5' // 背景颜色,不要在前面加#号
      }
    },
    font: {
      name: '宋体',
      sz: 16,
      color: { rgb: 'FFFFFFFF' },
      bold: false,
      italic: false,
      underline: false
    },
    alignment: alignCenter
  }
  // 设置停机原因的样式
  ws['A2'].s = {
    font: {
      name: '宋体',
      sz: 12,
      color: { rgb: '#FFFF0000' },
      bold: true,
      italic: false,
      underline: false
    },
    alignment: alignCenter
  }
  // 设置所在位置的样式
  ws['A3'].s = {
    font: {
      name: '宋体',
      sz: 12
    }
  }
  // 获取需要编程斑马纹的表格列名称
  const styleColName = getStyleColName()

  Object.keys(ws).forEach(item => {
    // 设置表头的样式
    if (/[A-Z]+4$/.test(item)) {
      ws[item].s = {
        border: borderAll,
        fill: {
          fgColor: {
            rgb: 'FFB4C6E7' // 背景颜色,不要在前面加#号
          }
        },
        font,
        alignment: alignCenter
      }
    } else if (item.replace(/[^0-9]/ig, '') > 4 && /^A\d+/.test(item)) {
      // 设置内容区第一行的样式
      ws[item].s = {
        font,
        border: borderAll,
        alignment: alignCenter
      }
    } else if (item.replace(/[^0-9]/ig, '') > 4 && styleColName.indexOf(item.replace(/[^a-zA-Z]/g, '')) > -1) {
      // 设置内容区斑马纹的样式
      ws[item].s = {
        border: borderAll,
        fill: {
          fgColor: {
            rgb: 'FFE7E6E6' // 背景颜色,不要在前面加#号
          }
        },
        font,
        alignment: {
          horizontal: 'left',
          vertical: 'center'
        }
      }
    } else if (item.replace(/[^0-9]/ig, '') > 4) {
      // 设置其余的单元格
      ws[item].s = {
        font,
        border: borderAll
      }
    }
  })
}

export function exportUtilizationRateExcel (companyName, stopReason, position, tableData, theadList, sheetName, excelName) {
  const data = tableData.data
  const length = 8
  // 合并公司名称
  const companyMerge = _getMergeConfig(0, 0, length, 0)
  // 合并停机原因单元格
  const stopReasonMerge = _getMergeConfig(0, 1, length, 1)
  // 合并所在位置单元格
  const positionMerge = _getMergeConfig(0, 2, length, 2)
  // 获取标题的合并配置和内容
  const { titleDate, titleMerge } = _getTitleInfo(data, theadList)
  // 获取内容区的合并配置
  const infoMerge = _getInfoMerge(data)
  // 获取内容区内容
  const infoData = _getInfoData(data)
  // 添加标题，停机原因，所在位置, 标题栏的数据
  const ws = XLSX.utils.aoa_to_sheet([[companyName], [stopReason], [position], titleDate, ...infoData])

  ws['!cols'] = calcColWidth(infoData)
  // 添加合并的config
  ws['!merges'] = [companyMerge, stopReasonMerge, positionMerge, ...titleMerge, ...infoMerge]
  // 生成样式
  _generateStyle(ws)
  // 创建一个空的sheet
  const wb = XLSX.utils.book_new()
  // 添加sheet
  XLSX.utils.book_append_sheet(wb, ws, sheetName)
  const wbout = XLSXStyle.write(wb, {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary'
  })
  saveAs(new Blob([s2ab(wbout)], {
    type: 'application/octet-stream'
  }), `${excelName}.xlsx`)
}
